﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace iNet.Collections
{
	/// <summary>
	/// 將元素型別轉換的列表。
	/// </summary>
	/// <typeparam name="TOut">轉換後的元素型別。</typeparam>
	/// <typeparam name="TIn">轉換前的元素型別。</typeparam>
	public class TypeConvertedList<TOut, TIn> : IList<TOut>, INotifyCollectionChanged
	{
		#region 欄位
		readonly IList<TIn> _List;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 TypeConvertedList 執行個體。
		/// </summary>
		/// <param name="list">原始列表。</param>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)。</exception>
		public TypeConvertedList(IList<TIn> list)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");

			//初始化欄位
			_List = list;

			//事件連結
			INotifyCollectionChanged collection = (list as INotifyCollectionChanged);
			if (collection != null)
				collection.CollectionChanged += this.OnSourceListChanged;
		}
		#endregion
		#region Add
		/// <summary>
		/// 將元素新增至列表後端。
		/// </summary>
		/// <param name="item">指定的元素。</param>
		public void Add(TOut item)
		{
			_List.Add((TIn)(object)item);
		}
		#endregion
		#region Clear
		/// <summary>
		/// 清除列表中的所有元素。
		/// </summary>
		public void Clear()
		{
			_List.Clear();
		}
		#endregion
		#region CollectionChanged
		/// <summary>
		/// 發生在集合改變後。
		/// </summary>
		public event NotifyCollectionChangedEventHandler CollectionChanged;
		#endregion
		#region Contains
		/// <summary>
		/// 確認列表中是否包含指定的元素。
		/// </summary>
		/// <param name="item">指定的元素。</param>
		/// <returns>True 表示列表中包含指定的元素，False 表示不包含。</returns>
		public bool Contains(TOut item)
		{
			if (item is TIn)
				return _List.Contains((TIn)(object)item);
			return false;
		}
		#endregion
		#region CopyTo
		/// <summary>
		/// 將列表中的元素複製至現有的一維陣列中。
		/// </summary>
		/// <param name="array">現有的一維陣列。</param>
		/// <param name="arrayIndex">起始索引值。</param>
		public void CopyTo(TOut[] array, int arrayIndex)
		{
			//確認參數
			if (array == null)
				throw new ArgumentNullException("array");

			//複製資料
			TIn[] originalArray = new TIn[array.Length];
			_List.CopyTo(originalArray, arrayIndex);

			//轉換型別
			for (int i = arrayIndex + _List.Count - 1; i >= arrayIndex; --i)
				array[i] = (TOut)(object)originalArray[i];
		}
		#endregion
		#region Count
		/// <summary>
		/// 取得列表中的元素個數。
		/// </summary>
		public int Count
		{
			get
			{
				return _List.Count;
			}
		}
		#endregion
		#region GetEnumerator
		/// <summary>
		/// 取得列舉元素的 System.Collections.Generic.IEnumerator&lt;TOut&gt; 介面。
		/// </summary>
		/// <returns>System.Collections.Generic.IEnumerator&lt;TOut&gt; 介面。</returns>
		public IEnumerator<TOut> GetEnumerator()
		{
			return new Enumerator<TOut>(_List.GetEnumerator());
		}
		#endregion
		#region IEnumerable.GetEnumerator
		IEnumerator IEnumerable.GetEnumerator()
		{
			return _List.GetEnumerator();
		}
		#endregion
		#region IndexOf
		/// <summary>
		/// 確認指定的元素在列表中的位置。
		/// </summary>
		/// <param name="item">指定的元素。</param>
		/// <returns>元素在列表中的索引位置。</returns>
		public int IndexOf(TOut item)
		{
			//確認參數
			if (item == null)
				throw new ArgumentNullException("item");

			//確認位置
			if (item is TIn)
				return _List.IndexOf((TIn)(object)item);
			return -1;
		}
		#endregion
		#region Insert
		/// <summary>
		/// 將元素插入至列表的指定位置。
		/// </summary>
		/// <param name="index">插入列表中的索引位置。</param>
		/// <param name="item">指定的元素。</param>
		public void Insert(int index, TOut item)
		{
			_List.Insert(index, (TIn)(object)item);
		}
		#endregion
		#region IsReadOnly
		/// <summary>
		/// 取得列表是否為唯讀。
		/// </summary>
		public bool IsReadOnly
		{
			get
			{
				return _List.IsReadOnly;
			}
		}
		#endregion
		#region OnSourceListChanged
		void OnSourceListChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			if (this.CollectionChanged != null)
				this.CollectionChanged(this, e);
		}
		#endregion
		#region Remove
		/// <summary>
		/// 從列表中移除指定的元素。
		/// </summary>
		/// <param name="item">指定的元素。</param>
		/// <returns>True 表示移除成功，False 表示失敗。</returns>
		public bool Remove(TOut item)
		{
			if (item is TIn)
				return _List.Remove((TIn)(object)item);
			return false;
		}
		#endregion
		#region RemoveAt
		/// <summary>
		/// 移除列表中指定位置的元素。
		/// </summary>
		/// <param name="index">指定的索引位置。</param>
		public void RemoveAt(int index)
		{
			_List.RemoveAt(index);
		}
		#endregion
		#region this[index]
		/// <summary>
		/// 取得或設定列表中指定位置的元素。
		/// </summary>
		/// <param name="index">指定的索引位置。</param>
		public TOut this[int index]
		{
			get
			{
				return (TOut)(object)_List[index];
			}
			set
			{
				_List[index] = (TIn)(object)value;
			}
		}
		#endregion
	}
}
